x11: Fallback to emulated window dragging for touch devices
authorCarlos Garnacho <carlosg@gnome.org>
Thu, 13 Mar 2014 19:19:26 +0000 (20:19 +0100)
committerCarlos Garnacho <carlosg@gnome.org>
Mon, 17 Mar 2014 17:19:44 +0000 (18:19 +0100)
Sadly, EWMH moveresize mechanism can't work with touch devices for two
reasons:

1) As a mutter implementation detail, the device is queried in order
to check whether the dragging button is still pressed. Touch devices
won't report the button 1 being pressed through pointer emulation.
2) Even bypassing that check, on X11 touch events are selected prior
to sequences being started, either through XISelectEvents or
XIGrabTouchBegin, no late registering through active grabs is allowed,
as WMs do on reaction to EWMH moveresize messages.

So for the time being, make touch devices fallback on emulated window
dragging, which at least allows for moving windows.

https://bugzilla.gnome.org/show_bug.cgi?id=709914

gdk/x11/gdkwindow-x11.c

index 5696e95bf124fd25728ae58f7532ea04981340ea..08ef713080c74a8fd1f414e61b4b91e0f07e3ac4 100644 (file)
@@ -5303,6 +5303,24 @@ emulate_move_drag (GdkWindow     *window,
   create_moveresize_window (mv_resize, timestamp);
 }
 
+static gboolean
+_should_perform_ewmh_drag (GdkWindow *window,
+                           GdkDevice *device)
+{
+  GdkPointerWindowInfo *info;
+  GdkDisplay *display;
+
+  display = gdk_window_get_display (window);
+  info = _gdk_display_get_pointer_info (display, device);
+
+  if ((!info->last_slave || gdk_device_get_source (info->last_slave) != GDK_SOURCE_TOUCHSCREEN) &&
+      gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
+                                           gdk_atom_intern_static_string ("_NET_WM_MOVERESIZE")))
+    return TRUE;
+
+  return FALSE;
+}
+
 static void
 gdk_x11_window_begin_resize_drag (GdkWindow     *window,
                                   GdkWindowEdge  edge,
@@ -5316,8 +5334,8 @@ gdk_x11_window_begin_resize_drag (GdkWindow     *window,
       !WINDOW_IS_TOPLEVEL_OR_FOREIGN (window))
     return;
 
-  if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
-                                          gdk_atom_intern_static_string ("_NET_WM_MOVERESIZE")))
+  /* Avoid EWMH for touch devices */
+  if (_should_perform_ewmh_drag (window, device))
     wmspec_resize_drag (window, edge, device, button, root_x, root_y, timestamp);
   else
     emulate_resize_drag (window, edge, device, button, root_x, root_y, timestamp);
@@ -5341,8 +5359,8 @@ gdk_x11_window_begin_move_drag (GdkWindow *window,
   else
     direction = _NET_WM_MOVERESIZE_MOVE;
 
-  if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
-                                          gdk_atom_intern_static_string ("_NET_WM_MOVERESIZE")))
+  /* Avoid EWMH for touch devices */
+  if (_should_perform_ewmh_drag (window, device))
     wmspec_moveresize (window, direction, device, button, root_x, root_y, timestamp);
   else
     emulate_move_drag (window, device, button, root_x, root_y, timestamp);